
.686p
.Model Flat,StdCall
Option CaseMap :None

VMExitHandler		Proto :DWORD, :DWORD
StartVT	Proto :DWORD

.CODE

HVM_SAVE_ALL_NOSEGREGS MACRO
		pushfd 
        push edi
        push esi
        push ebp
        push esp ;        push esp
        push ebx
        push edx
        push ecx
        push eax
ENDM

HVM_RESTORE_ALL_NOSEGREGS MACRO
        pop eax
        pop ecx
        pop edx
        pop ebx
        pop esp ;        pop esp
        pop ebp
        pop esi
        pop edi    
        popfd
ENDM

_ReadMSR	Proc	MSRIndex
		mov	ecx,MSRIndex
		rdmsr
		ret
_ReadMSR	EndP

_WriteMSR	Proc	MSRIndex,LowPart,HighPart
		mov	ecx,MSRIndex
		mov	eax,LowPart
		mov	edx,HighPart
		wrmsr
		ret
_WriteMSR	EndP

_TSC	Proc
	rdtsc
	ret
_TSC	EndP

_CS	Proc
	mov	ax,cs
	ret
_CS	EndP

_DS	Proc
	mov	ax,ds
	ret
_DS	EndP

_ES	Proc
	mov	ax,es
	ret
_ES	EndP

_FS	Proc
	mov	ax,fs
	ret
_FS	EndP

_GS	Proc
	mov	ax,gs
	ret
_GS	EndP

_SS	Proc
	mov	ax,ss
	ret
_SS	EndP

_CR0	Proc
	mov	eax,cr0
	ret
_CR0	EndP

_CR2	Proc
	mov	eax,cr2
	ret
_CR2	EndP

_CR3	Proc
	mov	eax,cr3
	ret
_CR3	EndP

_CR4	Proc
	mov	eax,cr4
	ret
_CR4	EndP

_SetCR0	Proc	rCR0
	mov	eax,rCR0
	mov	cr0,eax
	ret
_SetCR0	EndP

_SetCR2	Proc	rCR2
	mov	eax,rCR2
	mov	cr2,eax
	ret
_SetCR2	EndP

_SetCR3	Proc	rCR3
	mov	eax,rCR3
	mov	cr3,eax
	ret
_SetCR3	EndP

_SetCR4	Proc	rCR4
	mov	eax,rCR4
	mov	cr4,eax
	ret
_SetCR4	EndP

_CpuId	Proc	Func,pEax,pEbx,pEcx,pEdx
	pushad
	mov	eax,Func
	cpuid
	mov	esi,pEax
	mov	dword ptr [esi],eax
	mov	esi,pEbx
	mov	dword ptr [esi],ebx
	mov	esi,pEcx
	mov	dword ptr [esi],ecx
	mov	esi,pEdx
	mov	dword ptr [esi],edx
	popad
	ret
_CpuId	EndP

_VmxOn	Proc	PhyVMXOnPtrLow,PhyVMXOnPtrHigh
	push	PhyVMXOnPtrHigh
	push	PhyVMXOnPtrLow
	vmxon	qword ptr [esp]
	add	esp,8
	ret
_VmxOn	EndP

_VmFailInvalid	Proc	uses ecx
		pushfd
		pop	eax
		xor	ecx,ecx
		bt	eax,0	;RFLAGS.CF
		adc	cl,cl
		mov	eax,ecx
		ret
_VmFailInvalid	EndP

_VmFailValid	Proc	uses ecx
		pushfd
		pop	eax
		xor	ecx,ecx
		bt	eax,6	;RFLAGS.ZF
		adc	cl,cl
		mov	eax,ecx
		ret
_VmFailValid	EndP

_VmClear PROC _PhyVMCSPtrLow, _PhyVMCSPtrHigh
	
	PUSH  _PhyVMCSPtrHigh
	PUSH  _PhyVMCSPtrLow
	VMCLEAR QWORD PTR [ESP]
	ADD ESP, 8
	RET
	
_VmClear ENDP

_VmPtrLd PROC _PhyVMCSPtrLow, _PhyVMCSPtrHigh

	PUSH _PhyVMCSPtrHigh
	PUSH _PhyVMCSPtrLow
	VMPTRLD QWORD PTR [ESP]
	ADD ESP, 8
	RET

_VmPtrLd ENDP

_WriteVMCS	Proc	uses ecx Field,Value
		mov	eax,Field
		mov	ecx,Value
		vmwrite	eax,ecx
		ret
_WriteVMCS	EndP

_ReadVMCS	Proc	uses ecx Field
		mov	eax,Field
		vmread	ecx,eax
		mov	eax,ecx
		ret
_ReadVMCS	EndP

_Eflags	Proc
	pushfd
	pop	eax
	ret
_Eflags	EndP

_IdtBase	Proc
		Local	idtr[6]:BYTE
		sidt	idtr
		mov	eax,dword ptr idtr[2]
		ret
_IdtBase	EndP

_IdtLimit	Proc
		Local	idtr[6]:BYTE
		sidt	idtr
		mov	ax,word ptr idtr[0]
		ret
_IdtLimit	EndP

_GdtBase	Proc
		Local	gdtr[6]:BYTE
		sgdt	gdtr
		mov	eax,dword ptr gdtr[2]
		ret
_GdtBase	EndP

_GdtLimit	Proc
		Local	gdtr[6]:BYTE
		sgdt	gdtr
		mov	ax,word ptr gdtr[0]
		ret
_GdtLimit	EndP

_Ldtr	Proc
		sldt	ax
		ret
_Ldtr	EndP

_TrSelector	Proc
		str	ax
		ret
_TrSelector	EndP

_VmLaunch	Proc
		vmlaunch
		ret
_VmLaunch	EndP

_Invd	Proc
	invd
	ret
_Invd	EndP

;_StopVirtualization	Proc
;			pushad
;			pushfd
;			push	ebp
;			mov	eax,'QUIT'
;			mov	ebx,'VMXI'
;			mov	ecx,'CE  '
;			vmcall
;_StopVirtualization	EndP

_GuestEntryPoint	PROC
			POPFD
			POPAD
			RET
_GuestEntryPoint	EndP

_ExitEventHandler PROC
	
	CLI
	
	;;
	;; Save the registor
	;;
	
	;pushfd 
	push edi
	push esi
	push ebp
	push esp
	push ebx
	push edx
	push ecx
	push eax
	
	;;
	;; call event handler
	;;
	
	MOV EBX, ESP
	LEA EAX, [ESP+20H]
	
	PUSH EBX
	PUSH EAX
	CALL VMExitHandler
	
	;;
	;; restore the registor
	;;

	pop eax
	pop ecx
	pop edx
	pop ebx
	pop ebp ;        pop esp
	pop ebp
	pop esi
	pop edi    
	;popfd
	
	;;
	;; Resume guest
	;;
	
	VMRESUME
	RET

_ExitEventHandler ENDP

_DisableWP PROC
	CLI
	MOV EAX, CR0
	AND EAX, 0FFFEFFFFH
	MOV CR0, EAX
_DisableWP ENDP

_EnableWP PROC
	MOV EAX, CR0
	OR EAX, 10000H
	MOV CR0, EAX
	STI
_EnableWP ENDP

_StopVT PROC

	PUSHAD
	PUSHFD
	PUSH EBP
	mov	EAX,'QUIT'
	VMCALL

_StopVT ENDP

_GuestExit	Proc
		POP	EBP
		POPFD
		POPAD
		RET
_GuestExit	EndP

_StartVT	Proc
			pushad
			pushfd

			push	esp
			call	StartVT
_StartVT 	EndP

_VmxOff	Proc	RegEsp,RegEip

	push	00006818h	;GUEST_IDTR_BASE
	call	_ReadVMCS
	push	eax
	push	00004812h	;GUEST_IDTR_LIMIT
	call	_ReadVMCS
	shl	eax,16
	push	eax
	lidt	fword ptr [esp+2]
	pop	eax
	pop	eax

	push	00006816h	;GUEST_GDTR_BASE
	call	_ReadVMCS
	push	eax
	push	00004810h	;GUEST_GDTR_LIMIT
	call	_ReadVMCS
	shl	eax,16
	push	eax
	lgdt	fword ptr [esp+2]
	pop	eax
	pop	eax

	push	00006800h	;GUEST_CR0
	call	_ReadVMCS
	mov	cr0,eax

	push	00006802h	;GUEST_CR3
	call	_ReadVMCS
	mov	cr3,eax

	push	00006804h	;GUEST_CR4
	call	_ReadVMCS
	mov	cr4,eax
	
	mov	eax,RegEip
	mov	ecx,RegEsp
	vmxoff
	leave
	mov	esp,ecx
	jmp	eax
_VmxOff	EndP

RegSetIdtr	Proc _base, _limit
		push	_base
		shl	_limit, 16
		push	_limit
		lidt	fword ptr [esp+2]
		pop	eax
		pop	eax
		ret
RegSetIdtr	EndP

END